package jp.sourceforge.akjrcp.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.PlatformUI;


public abstract class ExecutingControler{
	public static Log log=LogFactory.getLog(ExecutingControler.class);
	private boolean executing;
	private boolean canceling;
	//private ExecutingControlButton controlButton;
	private ExecutingControlSwitch executingControlSwitch;
	private List controls=new ArrayList();
	public void finishedExecute(){
	
	}

	
	public void executeOrCancel(){
		if(this.isExecuting()){
			this.canceldExecute();
		}else{
			this.execute();
		}
	}
	
	public void execute(){
		log.info("execute");
		executing=true;
		canceling=false;
		executingControlSwitch.updateCancelMode();
		//controlButton.setText(controlButton.getCancelLabel());
		disableControls();
		//beforeExecute
		beforeExecute();
		new InExecute().start();
	}
	
	/*
	 * call from main Thread.
	 */
	public class InExecute extends Thread{
		public void run(){
		
			try{
			inExecute();
			}catch(Exception e){
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
			
			if(!canceling){
				System.out.println("finish");
				PlatformUI.getWorkbench().getDisplay().syncExec(new FinishExecute());
			}
		}
	}
	
	public class CancelExecute extends Thread{
		public void run(){
			canceldExecute();
		}
	}
	
	public class FinishExecute extends Thread{
		public void run(){
			finishExecute();//for update buttons
			afterExecute();
		}
	}
	
	
	public class UpdateControlSwitch extends Thread{
		public void run(){
			updateControlSwitch();
		}
	}
	
	public void updateControlSwitch(){
		if(executingControlSwitch!=null){
		if(canExecute()){
			executingControlSwitch.setEnabled(true);
		}else{
			executingControlSwitch.setEnabled(false);
		}
		}
	}
	public abstract boolean canExecute();
	public abstract void afterExecute();
	public abstract void beforeExecute();//get parameters.
	public abstract void inExecute();
	public abstract void cancelExecuting();//kill process something
	
	public void finishExecute(){
		log.info("finishExecute");
		executing=false;
		executingControlSwitch.updateExecuteMode();
		
		enableControls();
	}
	
	public void canceldExecute(){
		canceling=true;
		cancelExecuting();
		
		
		executing=false;
		executingControlSwitch.updateExecuteMode();
		
		enableControls();
	}

	public boolean isExecuting() {
		return executing;
	}

	public void setExecuting(boolean executing) {
		this.executing = executing;
	}

	
	public void addControl(Control control){
		controls.add(control);
	}
	
	public void enableControls(){
		Iterator iter=controls.iterator();
		while(iter.hasNext()){
			Control control=(Control) iter.next();
			control.setEnabled(true);
		}
	}
	
	public void disableControls(){
		Iterator iter=controls.iterator();
		while(iter.hasNext()){
			Control control=(Control) iter.next();
			control.setEnabled(false);
		}
	}

	public boolean isCanceling() {
		return canceling;
	}

	public void setCanceling(boolean canceling) {
		this.canceling = canceling;
	}
	
	public interface ExecutingControlSwitch{
		public void setEnabled(boolean bool);
		public void updateExecuteMode();
		public void updateCancelMode();
	}

	public static class ExecutingControlButton extends Composite implements ExecutingControlSwitch{
		private ExecutingControler controler;
		private String executeLabel;
		private String cancelLabel;
		private Button button;
		public ExecutingControlButton(Composite arg0, int arg1,ExecutingControler controler,String executeLabel,String cancelLabel) {
			super(arg0, arg1);
			this.setLayout(new FillLayout());
			button=new Button(this,SWT.NONE);
			
			this.cancelLabel=cancelLabel;
			this.executeLabel=executeLabel;
			this.controler=controler;
			button.setText(executeLabel);
			this.setEnabled(false);
			controler.setExecutingControlSwitch(this);
			button.addSelectionListener(new SelectionListener(){

				public void widgetDefaultSelected(SelectionEvent e) {
					
				}

				public void widgetSelected(SelectionEvent e) {
					if(getControler().isExecuting()){
						getControler().canceldExecute();
					}else{
						getControler().execute();
					}
				}
				
			});
		}
		public void setEnabled(boolean bool){
			super.setEnabled(bool);
			button.setEnabled(bool);
		}

		public String getCancelLabel() {
			return cancelLabel;
		}

		public void setCancelLabel(String cancelLabel) {
			this.cancelLabel = cancelLabel;
		}

		public ExecutingControler getControler() {
			return controler;
		}

		public void setControler(ExecutingControler controler) {
			this.controler = controler;
		}

		public String getExecuteLabel() {
			return executeLabel;
		}

		public void setExecuteLabel(String executeLabel) {
			this.executeLabel = executeLabel;
			updateExecuteMode();
		}

		public void updateCancelMode() {
			button.setText(cancelLabel);
		}

		public void updateExecuteMode() {
			button.setText(executeLabel);
		}
		
	}

	public ExecutingControlSwitch getExecutingControlSwitch() {
		return executingControlSwitch;
	}

	public void setExecutingControlSwitch(
			ExecutingControlSwitch executingControlSwitch) {
		this.executingControlSwitch = executingControlSwitch;
	}
}

